国际化-RTL

May 26, 2019

背景

今天看到一个TS的写法

enum SOME_ENUM {
A = 1,
B = 2
}
type CodeType = typeof SOME_ENUM[keyof typeof SOME_ENUM];
type CodeType1 = (typeof SOME_ENUM)[keyof typeof SOME_ENUM];

这两个等价么?发现对这两个操作符的认识还是不够,于是做了整理如下

1. keyof 的作用

获取对象类型的键的联合类型

    interface Person {
      name: string;
      age: number;
    }
    type PersonKeys = keyof Person; // "name" | "age"

这常用于限制函数参数必须为对象的有效键:

function getProperty<T, K extends keyof T>(obj: T, key: K) {
  return obj[key];
}

2. typeof 的作用

获取变量或表达式的类型

const person = { name: "Alice", age: 30 };
type PersonType = typeof person; // { name: string; age: number }

这在避免重复定义类型时非常有用,尤其是当变量结构复杂时。

3. 结合使用 keyof 和 typeof

动态生成键的联合类型

const config = { host: "localhost", port: 8080 };
type ConfigKeys = keyof typeof config; // "host" | "port"

当 config 结构变化时,ConfigKeys 会自动更新。

4. 典型应用场景

  • 类型安全的对象操作: 限制函数只能访问对象的有效属性,避免拼写错误:
const obj = { id: 1, value: "test" };
function logKey(key: keyof typeof obj) {
	console.log(obj[key]);
}
logKey("id");    // 正确
logKey("name");  // 错误:类型不匹配
  • 映射类型和工具类型keyof 常用于构建映射类型,如内置的 Partial<T> 或自定义类型:
type Readonly<T> = {
    readonly [K in keyof T]: T[K];
};
  • 枚举键的提取: 获取枚举类型的键名字符串联合:
enum Direction { Up, Down }
type DirectionKeys = keyof typeof Direction; // "Up" | "Down"

5. 注意事项

  • 联合类型的 keyof: 对联合类型使用 keyof 会得到所有成员键的联合:
type A = { a: string } | { b: number };
type Keys = keyof A; // "a" | "b"
  • typeof 的上下文区分: 在类型上下文中使用 typeof(提取类型),而非值上下文中的 JavaScript typeof(返回类型字符串)

总结

  • keyof:从类型中提取键的联合类型,增强属性访问的安全性。
  • typeof:从值中提取类型,避免重复定义类型。
  • 联合使用:动态生成与变量结构一致的键类型,提升代码可维护性。